
/*
 * @项目名称: 模板开发
 * @FilePath: /meek/src/renderer/render/polygonrender.js
 * @Author: 
 * @Date: 2017-03-23T11:12:12+08:00
 * @LastEditors: 447508585@qq.com
 * @LastEditTime: 2023-03-13 15:44:14
 * Copyright (c) 2018-2022 
 */
                                                    
/**
 * Created by zhangyong on 2017/3/20.
 */
import Geometry from '../../geometry/geometry'
import GeometryRender from '../render/geomertyrender'
import LineStyle from '../../style/linestyle'
import {
  Transform
} from '../../data/matrix/transform'
import {
  colorToString
} from '../../utils/helpers'
import {
  drawPoint,
  drawPointIndexes
} from './drawPoint';
import { drawCenterPoint } from './circlerender'
import { segmentsIntr } from '../../utils/intersection'

import TextStyle from '../../style/textstyle'

import BezierRender from './bezierrender';
export default class PolygonRender extends GeometryRender {

  constructor(context) {
    super(context)
  }

  /**
   * Render a polygon
   * @param feature
   * @param transform
   * @returns {boolean}
   */
  render(feature, renderStyle, transform) {
    if (!feature) {
      return
    }
    const ctx = this.context
    const styleArray = renderStyle
    const geometry = feature.geometry

    const transform2D = Transform.transform2D
    let geometryCoordinages = geometry.getCoordinates()
    if (geometry.geometryType === Geometry.EXTENT) {
      geometryCoordinages = [geometryCoordinages]
    }

    if (!geometryCoordinages) {
      return false
    }

    if (geometryCoordinages.length === 0) {
      return false
    }
    // TODO find a way to cache the rendered data
    let coordinates = []
    let renderCoords = []

    if (this._pixelCoordinates &&
      this.equalsTransform(transform, this.renderedTransform)) {
      renderCoords = this._pixelCoordinates
    } else {
      if (geometry.geometryType === Geometry.MULTI_POLYGON || geometry.geometryType === Geometry.CUBE) {
        let polygonCoords = []
        // 遍历各个多边形
        geometryCoordinages.forEach(polygon => {
          polygon.forEach(rings => {
            rings.forEach(points => {
              let coordinate = transform2D(
                points, 0, points.length, 2,
                transform)

              coordinate[0] = (coordinate[0] + 0.5) | 0
              coordinate[1] = (coordinate[1] + 0.5) | 0

              coordinates.push(coordinate)
            })

            polygonCoords.push(coordinates)
            coordinates = []
          })

          renderCoords.push(polygonCoords)
          polygonCoords = []
        })
        this.renderMutilPolygon(ctx, styleArray, renderCoords, feature)

      } else {
        // 遍历多边形各个环
        geometryCoordinages.forEach(rings => {
          rings.forEach(points => {
            let coordinate = transform2D(
              points, 0, points.length, 2,
              transform)
            coordinate[0] = (coordinate[0] + 0.5) | 0
            coordinate[1] = (coordinate[1] + 0.5) | 0

            coordinates.push(coordinate)
          })

          renderCoords.push(coordinates)
          coordinates = []
        })


        let bezierdata = feature.geometry.bezier;
        if (bezierdata && bezierdata.length) {
          let transformCoords = [];
          bezierdata.forEach(item => {
            let data = geometry.getBezierItem(item);
            let coordinateTemp = [];
            data.renderPoints.forEach(function(points){
              let coordinate = transform2D(
                points, 0, points.length, 2,
                transform)
          
              coordinate[0] = (coordinate[0] + 0.5 ) | 0
              coordinate[1] = (coordinate[1] + 0.5 ) | 0
              coordinateTemp.push(coordinate);
            })
            transformCoords.push({
              ringIndex: data.ringIndex,
              start: data.start,
              renderPoints: coordinateTemp
            })
          })
          this.renderPolygonWidthBezier(ctx, styleArray, renderCoords, transformCoords, feature)
        } else {
          this.renderPolygon(ctx, styleArray, renderCoords, geometry)
        }
        drawPoint(ctx, renderCoords, feature, styleArray)
        this.renderCenterPoint(ctx, renderCoords, feature, styleArray);
        this.drawPointIndexes(ctx, renderCoords, feature);



        //this.renderPolygon(ctx, styleArray, renderCoords)
      }

      //this.renderPolygon(ctx, styleArray, renderCoords, geometry)
    }
    // this.drawBezier(feature, renderStyle, transform);
    this._pixelCoordinates = renderCoords
    Transform.setFromArray(this.renderedTransform, transform)
    return true
  }


  /**
   *
   * @param ctx
   * @param styleArray
   * @param renderCoords
   */
  renderMutilPolygon(ctx, styleArray, renderCoords) {
    renderCoords.forEach(polygon => {
      this.renderPolygon(ctx, styleArray, polygon)
    })
  }

  /**
   *
   * @param ctx
   * @param styleArray
   * @param renderCoords
   */
  renderPolygon(ctx, styleArray, renderCoords) {
    const len = styleArray.length
    for (let i = 0; i < len; i++) {
      let styleObj = styleArray[i]

      let renderOptions = {
        coordinates: renderCoords,
        fillStyle: colorToString(styleObj.color, styleObj.alpha),
        borderStyle: styleObj.borderStyle
      }

      this.drawStylePolygon(ctx, renderOptions)
    }
  }

  renderPolygonWidthBezier(ctx, styleArray, renderCoords, transformCoords, feature) {
    const len = styleArray.length

    const map = {};
    transformCoords.forEach(item => {
      if (!map[item.ringIndex]) {
        map[item.ringIndex] = {};
      }
      map[item.ringIndex][item.start] = item;
    })
    for (let i = 0; i < len; i++) {
      let styleObj = styleArray[i]

      let renderOpt = {
        coordinates: renderCoords,
        fillStyle: colorToString(styleObj.color, styleObj.alpha),
        borderStyle: styleObj.borderStyle
      }

      ctx.save()

      if (renderOpt.fillStyle) {
        ctx.fillStyle = renderOpt.fillStyle
      }

      const borderStyle = renderOpt.borderStyle;
      if (borderStyle) {
        ctx.strokeStyle = colorToString(borderStyle.color, borderStyle.alpha)
        ctx.lineWidth = borderStyle.width
        if (borderStyle.style === LineStyle.DASH) {
          ctx.setLineDash([5, 5])
        } else if (borderStyle.style === LineStyle.DASHDOT) {
          ctx.setLineDash([10, 3, 3, 3]);
        }
      }

      const coords = renderOpt.coordinates

      const virtualLines = [];
      const controlPoints = [];
      coords.forEach((coordinates, index) => {
        if (index === 0) {
          ctx.beginPath()
        }
        
        ctx.moveTo(coordinates[0][0], coordinates[0][1])
        for (let i = 0,ii = coordinates.length ; i < ii - 1 ; i++) {
          if (map[index] && map[index][i]) {
            const renderPs = map[index][i].renderPoints;
            BezierRender.drawBezierPath(ctx, {
              coordinates: renderPs
            })
            virtualLines.push(renderPs);
            //绘制控制点
            controlPoints.push(...renderPs.slice(1, renderPs.length - 1));
          } else {
            ctx.lineTo(coordinates[i + 1][0],coordinates[i + 1][1])
          }
          
        }
        ctx.closePath()
        
      })
      ctx.stroke();
      ctx.fill()
      
      //添加贝塞尔黄色虚线
      const color = ctx.strokeStyle;
      virtualLines.forEach((item, index) => {
        if (feature.styleHighLight) {
          ctx.beginPath();
          ctx.strokeStyle = color;
          ctx.setLineDash([5, 5])
          item.forEach((point, index) => {
            if (index == 0) {
              ctx.moveTo(...point);
            }
            ctx.lineTo(...point);
          })
          ctx.stroke();
        }
          

        ctx.beginPath();
        ctx.setLineDash([5, 5])
        ctx.strokeStyle = '#FFFF00';
        ctx.lineWidth = 1;
        ctx.moveTo(...item[0]);
        ctx.lineTo(...item[item.length - 1]);
        ctx.stroke();
      })
      
      //绘制控制点
      if (feature.styleHighLight) { 
        ctx.fillStyle = '';
        ctx.setLineDash([]);
        BezierRender.drawPoint(ctx, {
          coordinates: controlPoints
        }, feature)
      }
      
      
      ctx.restore()
    }
  }

  /**
   * 绘制多边形，需要注意多边形各个环的绘制
   * @param ctx
   * @param renderOpt
   */
  drawStylePolygon(ctx, renderOpt) {
    ctx.save()

    if (renderOpt.fillStyle) {
      ctx.fillStyle = renderOpt.fillStyle
    }

    const borderStyle = renderOpt.borderStyle
    if (borderStyle) {
      ctx.strokeStyle = colorToString(borderStyle.color, borderStyle.alpha)
      ctx.lineWidth = borderStyle.width
      if (borderStyle.style === LineStyle.DASH) {
        ctx.setLineDash([5, 5])
      } else if (borderStyle.style === LineStyle.DASHDOT) {
        ctx.setLineDash([10, 3, 3, 3]);
      }
    }

    const coords = renderOpt.coordinates
    coords.forEach((coordinates, index) => {
      if (index === 0) {
        ctx.beginPath()
      }

      ctx.moveTo(coordinates[0][0], coordinates[0][1])
      for (let k = 1, kk = coordinates.length; k < kk; k++) {
        let cd = coordinates[k]
        if (cd) {
          ctx.lineTo(cd[0], cd[1])
        }
      }

      ctx.closePath()
    })

    ctx.fill()
    ctx.stroke()
    ctx.restore()
  }

  drawPointIndexes(ctx, renderCoords, feature) {
    if (!feature.showPointIndex) {
      return 
    }
    const pointIndexTextSize = feature.pointIndexTextSize
    renderCoords.forEach((coordinates, index) => {
      drawPointIndexes(ctx, coordinates.slice(0, -1),{pointIndexTextSize})
    })
  }

  renderCenterPoint(ctx, renderCoords, feature, styleArray) {
    if (!feature.centralPoint) {
      return ;
    }
    const len = styleArray.length;
    let coords = renderCoords[0];
    let centerPoint;
    if(coords.length >= 4) {
      centerPoint = segmentsIntr({
        x: coords[0][0],
        y: coords[0][1]
      }, {
        x: coords[2][0],
        y: coords[2][1]
      }, {
        x: coords[1][0],
        y: coords[1][1]
      }, {
        x: coords[3][0],
        y: coords[3][1]
      });
    }
    
    if (!centerPoint) {
      return ;
    }
    for (let i = 0; i < len; i++) {
      let styleObj = styleArray[i]

      let renderOptions = {
        fillStyle: colorToString(styleObj.color, styleObj.alpha),
        borderStyle: styleObj.borderStyle
      }
      drawCenterPoint(ctx, [centerPoint.x, centerPoint.y], renderOptions);
    }
  }
}
